home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / sthing.com / STHING.DOC < prev    next >
Encoding:
Text File  |  1990-10-28  |  24.0 KB  |  597 lines

  1.                 Turbo Pascal Access to the Covox Speech Thing
  2.                                 Kim Kokkonen
  3.                              TurboPower Software
  4.                                 October 1990
  5.  
  6. The Covox Speech Thing is a high-quality, cost effective system for adding
  7. speech capabilities to PC programs. For only about $80, you get an interface
  8. plug that connects to a PC's parallel port, an auxiliary speaker that connects
  9. to the interface plug, and the SmoothTalker TSR, which converts ASCII text
  10. into output instructions that generate good quality speech from the speaker.
  11. The Speech Thing package also includes capabilities for playing digitized
  12. (prerecorded) sounds as opposed to synthesized speech; STHING.DOC focuses on
  13. the speech synthesis capabilities.
  14.  
  15. Although Covox supplies a version of the SmoothTalker TSR that will run on
  16. 4.77MHz 8088-based PC's, the quality of the speech on such a machine is not
  17. very good. Realistically, you need an 8Mhz 8088 or a 286 or 386 machine to get
  18. good speech quality. When running on a 16MHz 286 machine (my development
  19. system), the Speech Thing produces speech quality that rivals that of $1000
  20. dedicated speech processing systems.
  21.  
  22. The programming interface that Covox supplies for the Speech Thing is aimed
  23. toward Basic and C programmers. This document describes a Turbo Pascal unit,
  24. STHING, which makes it easy for Turbo Pascal (version 5.0 or later)
  25. programmers to add synthesized speech capabilities to their programs. It also
  26. describes two programs, STRES and TPTALK, which demonstrate some of the
  27. capabilities of the unit. We assume throughout that you have the Covox Speech
  28. Thing User Manual to refer to as needed.
  29.  
  30. If you don't already have a Speech Thing, you can contact Covox as follows:
  31.  
  32.   Covox, Inc.
  33.   675 Conger St.
  34.   Eugene, OR 97402
  35.  
  36.   tel: 503-342-1271
  37.   fax: 503-342-1283
  38.   bbs: 503-342-4135
  39.  
  40. The Turbo Pascal code provided here is Copyright (C) 1990 TurboPower Software,
  41. all rights reserved. We hereby grant rights to other programmers to use this
  42. code in their own programs, for personal or commercial use, at no charge. You
  43. may freely distribute the files contained in this archive, including
  44. STHING.DOC, STHING.PAS, STHING.ASM, STHING.OBJ, STRES.PAS, STRES.EXE, and
  45. TPTALK.PAS. You may *not* sell any of the files (with the exception of nominal
  46. handling fees charged by bulletin board operators and shareware software
  47. distributors) without the express written consent of TurboPower Software. The
  48. SPEECHV2 and SPEECHV3 programs and other parts of the Speech Thing itself are
  49. the property of Covox, Inc. See the Speech Thing license agreement for
  50. information about using these programs.
  51.  
  52.  
  53. Overview of the STHING Unit
  54. ---------------------------------------------------------------------------
  55. STHING is a Turbo Pascal unit that provides procedures and functions for
  56. accessing all of the speech synthesis capabilities of the Speech Thing. In
  57. order for STHING to work, you must first load either the SPEECHV2 or SPEECHV3
  58. memory resident program prior to calling the routines in STHING. It is not
  59. necessary for you to load Covox's STALK memory resident program, which is
  60. designed to make it easy for Basic programmers to access SPEECHVx. STALK is
  61. not necessary and in fact adds time and memory overhead for Turbo Pascal
  62. programs.
  63.  
  64. STHING's initialization block searches for the signature of the SPEECHVx TSR.
  65. If the signature isn't found, STHING's StLoaded function will return False and
  66. none of the other routines will do anything. (It's still safe to call them,
  67. however.) If the signature is found, STHING initializes the Speech Thing as
  68. follows:
  69.  
  70.   - speech output is sent to the LPT1 port
  71.   - speech tone, volume, pitch, and speed are set to default values
  72.   - the SPEECHV3 hook routine that determines which keystrokes can interrupt
  73.     speech is redirected to the STHING unit
  74.  
  75. All of these defaults may be changed by calling other routines provided by
  76. STHING. For explanation of the third item, see the section "Interrupting
  77. Speech in Progress" below.
  78.  
  79. The simplest program that should produce speech is the following:
  80.  
  81.   program Speak1;
  82.   uses
  83.     SThing;
  84.   begin
  85.     StSpeak('hello world');
  86.   end.
  87.  
  88. If your Speech Thing interface plug is attached to a parallel port other than
  89. LPT1, you need to add one more statement:
  90.  
  91.   program Speak2;
  92.   uses
  93.     SThing;
  94.   begin
  95.     StSetLptPort(2); {Sets up for LPT2}
  96.     StSpeak('hello world');
  97.   end.
  98.  
  99. The supplied programs STRES and TPTALK demonstrate other features of the
  100. STHING unit.
  101.  
  102. The routines in STHING can be organized in three groups:
  103.  
  104.   Basic Functions
  105.     - set output port
  106.     - set speech parameters
  107.     - speak an ASCII string
  108.     - modify ability to interrupt speech in progress
  109.     - unload SPEECHVx from memory
  110.  
  111.   Phonetic Speech Functions
  112.     - convert a text string to its phonetic representation
  113.     - speak a string in phonetic representation
  114.  
  115.   Dictionary Functions
  116.     - initialize or clear the dictionary
  117.     - add or remove an entry in the dictionary
  118.     - list the elements in the dictionary
  119.     - write or read a dictionary file
  120.  
  121. Detailed descriptions of each routine follow in the "STHING Reference Guide."
  122.  
  123.  
  124. Speech Dictionaries
  125. ---------------------------------------------------------------------------
  126. As Covox points out in its manual, the English language is notoriously tricky
  127. about pronunciation rules. The speech dictionary provides a means to improve
  128. the quality of synthesized speech for words that don't follow standard rules
  129. of pronunciation. Each entry in the dictionary contains a text string
  130. representing the normal spelling of the word, and a phonetic text string
  131. (using the SmoothTalker phonetic codes shown in Appendix A of the Covox
  132. manual) representing how you'd like the word to sound. SPEECHVx automatically
  133. substitutes the specified pronunciation whenever it encounters a dictionary
  134. word in the text stream passed to it.
  135.  
  136. Here's a short program that demonstrates the use of a speech dictionary:
  137.  
  138.   program Dict;
  139.   uses
  140.     SThing;
  141.   var
  142.     txst : string;
  143.     phst : string;
  144.   begin
  145.     if not StLoaded then
  146.       halt;
  147.  
  148.     {Clear the dictionary. Redundant here}
  149.     StInitDict(True);
  150.  
  151.     {Speak a hard-to-pronounce word}
  152.     writeln('ASCII before adding to dictionary');
  153.     StSpeak('ascii');
  154.     readln;
  155.  
  156.     {Add the correct pronunciation to the dictionary}
  157.     if not StInsertDict('ascii', 'AEskIY') then
  158.       writeln('out of memory');
  159.  
  160.     {Speak the word again}
  161.     writeln('ASCII after adding to dictionary');
  162.     StSpeak('ascii');
  163.     readln;
  164.  
  165.     {Display what's in the dictionary}
  166.     writeln('Contents of dictionary');
  167.     StInitDict(false);
  168.     StDumpDict(txst, phst);
  169.     while txst <> '' do begin
  170.       writeln('"', txst, '", "', phst, '"');
  171.       StDumpDict(txst, phst);
  172.     end;
  173.     readln;
  174.  
  175.     {Remove the word from the dictionary}
  176.     StRemoveDict('ascii');
  177.  
  178.     {Speak the word again}
  179.     writeln('ASCII after removing from dictionary');
  180.     StSpeak('ascii');
  181.     readln;
  182.   end.
  183.  
  184. When you add a dictionary entry, SPEECHVx allocates a block of memory to hold
  185. the entry. Normally SPEECHVx allocates this memory directly from the DOS free
  186. memory pool. Although that makes sense for C and Basic programs, it often
  187. doesn't work for Turbo Pascal because all available DOS memory is usually
  188. allocated for the Turbo Pascal heap. To deal with this issue, the STHING unit
  189. takes over the DOS interrupt ($21) and converts requests for DOS memory into
  190. equivalent requests to the Turbo Pascal heap manager. There is only one
  191. disadvantage to the approach: it isn't possible to deallocate the memory
  192. allocated for dictionary entries on the Turbo Pascal heap. If you have an
  193. application that needs to add and remove lots of dictionary entries, you
  194. should set STHING's boolean typed constant StAllocFromHeap to False as soon as
  195. your program starts. Note that in this case your program must use a $M
  196. directive to assure that there is free DOS memory space from which SPEECHVx
  197. can allocate dictionary entries.
  198.  
  199. One other point to keep in mind: a dictionary remains active for only so long
  200. as the program which created it remains active. That is, as soon as your
  201. program halts, the dictionary is cleared. (A dictionary created by a TSR
  202. remains active as long as the TSR remains loaded.) For this reason, it's
  203. usually important to save dictionaries to a dictionary file before an
  204. application halts and to reload them when the program starts.
  205.  
  206. Determining the best phonetic codes for a word is not a job for the impatient.
  207. However, in some cases it is well worth the effort. The StTextToPhonetic
  208. procedure will generate a first attempt at the codes by using SPEECHVx's own
  209. internal rules. Then you can modify the phonetic string by referring to
  210. Appendix A of the Speech Thing manual.
  211.  
  212.  
  213. Interrupting Speech in Progress
  214. ---------------------------------------------------------------------------
  215. When SPEECHV3 is loaded, you can interrupt speech in progress by pressing any
  216. key, with the exception of the Shift and Alt keys. SPEECHV2 does not offer
  217. this interrupt capability. SPEECHV3's behavior is a little annoying, at least
  218. for people who are accustomed to using WordStar editing keystrokes, because
  219. speech is interrupted when the Ctrl key is held down.
  220.  
  221. SPEECHV3 provides a hook to modify its behavior in this regard. Whenever it
  222. checks whether speech should be interrupted, it issues an interrupt $7E. If
  223. the int $7E handler returns AX <> 0, speech output will be aborted and control
  224. will return to the calling application.
  225.  
  226. The STHING unit takes over int $7E with a handler that provides the following
  227. behavior: any key that inserts a real keystroke into the keyboard buffer will
  228. interrupt speech. (This definition excludes the Ctrl, Alt, Shift, NumLock, and
  229. ScrollLock keys.) The keystroke causing the interruption remains in the
  230. keyboard buffer where it can be processed by the underlying application.
  231.  
  232. You can restore SPEECHV3's default behavior by calling STHING's StRestoreInt7E
  233. procedure. If you need different behavior, you can install your own int $7E
  234. handler. Be sure to study the handler in STHING.ASM before writing your own.
  235.  
  236.  
  237. STHING Reference Guide
  238. ---------------------------------------------------------------------------
  239. The procedures and functions of STHING are described here in alphabetical
  240. order.
  241.  
  242. -------------------------
  243.  
  244. procedure StDumpDict(var TextSt : string; var PhonSt : string);
  245.  
  246.   Call this routine repeatedly to retrieve all entries in the dictionary. The
  247.   text strings are returned in alphabetical order, always in uppercase. When
  248.   there are no more entries, TextSt returns an empty string. Call StInitDict
  249.   first to reset the internal dictionary position pointer. Example:
  250.  
  251.      StInitDict(False);
  252.      StDumpDict(TextSt, PhonSt);
  253.      while TextSt <> '' do begin
  254.        writeln(TextSt:40, PhonSt:40);
  255.        StDumpDict(TextSt, PhonSt);
  256.      end;
  257.  
  258. -------------------------
  259.  
  260. procedure StGetParams(var Tone, Volume, Pitch, Speed : Word);
  261.  
  262.   Returns the last speech parameters set. See StSetParams for more
  263.   information.
  264.  
  265. -------------------------
  266.  
  267. procedure StGrabInt7E;
  268.  
  269.   Modifies the abort-speech-on-keypressed behavior as described in the section
  270.   "Interrupting Speech in Progress" above. Since STHING calls this routine
  271.   automatically during initialization, you don't need to call it yourself
  272.   unless you are restoring and grabbing int $7E repeatedly, as in a TSR. See
  273.   STRES.PAS for an example. StGrabInt7E affects the behavior of SPEECHV3 only.
  274.  
  275. -------------------------
  276.  
  277. procedure StInitDict(Clear : Boolean);
  278.  
  279.   Reset the dictionary. If Clear = True, all entries are removed. If Clear =
  280.   False, the dictionary's internal position pointer is reset to prepare for an
  281.   alphabetical scan of the dictionary. See StDumpDict for an example.
  282.  
  283. -------------------------
  284.  
  285. function StInsertDict(TextSt : string; PhonSt : string) : Boolean;
  286.  
  287.   Insert a new entry in the dictionary. Returns False if insufficient memory.
  288.   If STHING's global typed constant StAllocFromHeap is True, StInsertDict
  289.   allocates memory space from the Turbo Pascal heap; otherwise it allocates
  290.   memory from the DOS free pool by using DOS function $48.
  291.  
  292. -------------------------
  293.  
  294. function StLoaded : Boolean;
  295.  
  296.   Returns True if SPEECHVx is loaded, False otherwise. The other STHING
  297.   routines don't do anything if StLoaded returns False.
  298.  
  299. -------------------------
  300.  
  301. procedure StPhoneticSpeak(St : string);
  302.  
  303.   Speak the specified phonetic string. See Appendix A of the Speech Thing
  304.   manual for information about acceptable phonetic codes. You should not
  305.   surround strings passed to StPhoneticSpeak with << and >> strings, which are
  306.   used only when mixing phonetic codes into normal text.
  307.  
  308. -------------------------
  309.  
  310. function StReadDictFile(FName : string) : Word;
  311.  
  312.   Read dictionary from a text file, returning status. The status value is a
  313.   standard Turbo Pascal IoResult code, with the following additions:
  314.  
  315.         8    StInsertDict returned False
  316.       106    Invalid dictionary file
  317.     65535    SPEECHVx is not loaded
  318.  
  319.   See StWriteDictFile for more information about the file format.
  320.  
  321. -------------------------
  322.  
  323. procedure StRemoveDict(TextSt : string);
  324.  
  325.   Remove an entry previously added to dictionary. If TextSt is not found in
  326.   the dictionary, StRemoveDict does nothing. If the STHING typed constant
  327.   StAllocFromHeap is True, heap space is NOT reclaimed by this call.
  328.  
  329. -------------------------
  330.  
  331. procedure StRestoreInt7E;
  332.  
  333.   Restore abort-speech-on-keypressed behavior to the default for SPEECHV3.
  334.  
  335. -------------------------
  336.  
  337. procedure StSetLptPort(LPTNumber : Byte);
  338.  
  339.   Set Speech Thing peripheral port for LPT 1, 2, or 3. STHING automatically
  340.   initializes for LPT1. Also see StSetPort, which allows specification of an
  341.   arbitrary port not associated with an LPT device.
  342.  
  343. -------------------------
  344.  
  345. procedure StSetParams(Tone, Volume, Pitch, Speed : Word);
  346.  
  347.   Set parameters, as follows:
  348.  
  349.              valid range  default
  350.              -----------  -------
  351.       Tone     0..1          0
  352.       Volume   0..9          5
  353.       Pitch    0..9          5
  354.       Speed    0..9          5
  355.  
  356.   StSetParams does not range-check the values it receives.
  357.  
  358. -------------------------
  359.  
  360. procedure StSetPort(Port : Word);
  361.  
  362.   Set peripheral port where speaker output goes. Note that the value passed
  363.   here is a hardware port number, not an LPT number. StSetPort interprets
  364.   Port=0 as a special case meaning the port associated with LPT1. StSetPort
  365.   should be called only when using a Voice Master or another Covox product to
  366.   emulate a Speech Thing.
  367.  
  368. -------------------------
  369.  
  370. procedure StSpeak(St : string);
  371.  
  372.   Speak the specified text string using the previously defined speech
  373.   parameters for tone, volume, pitch, and speed. Note that you can pass a
  374.   maximum of 255 characters at a time. If the text stream to speak exceeds 255
  375.   characters it is your responsibility to parse it into shorter chunks.
  376.  
  377.   StSpeak doesn't return until the string has been completely spoken, unless
  378.   the speech is interrupted by a keystroke.
  379.  
  380. -------------------------
  381.  
  382. procedure StTextToPhonetic(TextSt : string; var PhonSt : string);
  383.  
  384.   Returns the phonetic codes for the given text string, using SPEECHVx's
  385.   internal conversion rules. Note that the length of the phonetic codes often
  386.   exceeds that of the text string. It's your responsibility to limit TextSt's
  387.   length so that PhonSt doesn't overflow.
  388.  
  389. -------------------------
  390.  
  391. procedure StUnload;
  392.  
  393.   Unloads the resident copy of SPEECHV2 or SPEECHV3 from memory. After calling
  394.   StUnload, StLoaded will always return False. Note that you can unload
  395.   SPEECHV3 from the DOS command line by entering SPEECHV3 /Q. SPEECHV2 does
  396.   not offer this command line capability, but it may still be unloaded by
  397.   calling StUnload.
  398.  
  399. -------------------------
  400.  
  401. function StWriteDictFile(FName : string) : Word;
  402.  
  403.   Write current dictionary to a file, returning status. The status value is a
  404.   standard Turbo Pascal IoResult code, with the following addition:
  405.  
  406.     65535    SPEECHVx is not loaded
  407.  
  408.   A dictionary file is a standard text file, with each line representing one
  409.   dictionary entry or a comment. Blank lines and lines beginning with a
  410.   semicolon are treated as comments. Other lines must contain a text word
  411.   followed by one or more spaces followed by the phonetic representation
  412.   (which may contain embedded spaces). The case (upper or lower) of the text
  413.   word isn't important, but the case of the phonetic representation must
  414.   exactly match the codes given by Covox. Here's an example of a valid
  415.   dictionary file:
  416.  
  417. ;these entries just encode the standard pronunciations
  418. ARBITRARILY    AArbIXtrEHr4IXl3IY
  419. ARBITRATOR     AArbIXtr4EYDX3ER
  420. COMPUTER       kAXmpy4UWDX3ER
  421. DICTIONARY     dIHkSHAXn4EHr3IY
  422.  
  423.  
  424. TPTALK - simple demonstration of STHING
  425. ---------------------------------------------------------------------------
  426. TPTALK is a simple program that demonstrates the STHING unit. If you specify
  427. the name of an ASCII text file on the command line when you call TPTALK, it
  428. will read the file for you. If don't specify a file name, you can enter text
  429. and TPTALK will speak each line as you enter it and write the phonetic
  430. representation of the line.
  431.  
  432. In general, TPTALK does the same thing as the TALK program supplied with the
  433. Speech Thing. TPTALK accepts the following command line options:
  434.  
  435.      /?         show a list of options
  436.      /T n       specify tone (0 or 1)
  437.      /I n       specify pitch (0..9)
  438.      /S n       specify speed (0..9)
  439.      /V n       specify volume (0..9)
  440.      /L n       specify LPT port (1..3)
  441.  
  442. Unlike TALK, TPTALK won't load the SPEECHVx program if it isn't already
  443. loaded. Note that TPTALK needs only SPEECHV2 or SPEECHV3; it is *not*
  444. necessary to load STALK.
  445.  
  446. TPTALK is provided only in source code format. You can compile it by running
  447. the Turbo Pascal compiler and doing a make in the same directory where
  448. STHING.PAS and STHING.OBJ reside.
  449.  
  450.  
  451. STRES - a memory resident screen reader
  452. ---------------------------------------------------------------------------
  453. STRES is a memory resident program for reading text screens and speaking them
  454. via the Covox Speech Thing. Before loading STRES you must first load SPEECHV2
  455. or SPEECHV3. Note that it is *not* necessary to load Covox's STALK memory
  456. resident program.
  457.  
  458. STRES is loaded with the following command line:
  459.  
  460.   STRES [options] [dictionaryfile]
  461.  
  462. You may specify the following command line options:
  463.  
  464.   /?            display a help screen but don't make STRES resident
  465.   /L n          specify line printer port (1..3)
  466.   /S            speak installation messages
  467.   /U            unload STRES from memory
  468.  
  469. The optional dictionary file must be in the format described under the
  470. StWriteDictFile function above.
  471.  
  472. The following hot keys activate STRES once it has been loaded:
  473.  
  474.   [Ctrl-RightShift-R] for screen reader mode
  475.   [Ctrl-RightShift-S] to speak whole screen
  476.  
  477. In screen reader mode the following keys are supported:
  478.  
  479.   [Up]            read next line up
  480.   [Down]          read next line down
  481.   [Left]          read next character left
  482.   [Right]         read next character right
  483.   [Ctrl-Left]     read next word left
  484.   [Ctrl-Right]    read next word right
  485.   [Home]          move cursor to left edge of screen
  486.   [End]           move cursor to right edge of screen
  487.   [PgUp]          move cursor to top of screen
  488.   [PgDn]          move cursor to bottom of screen
  489.   [Enter],[Esc]   exit from reader mode
  490.  
  491. Although the cursor is moved while STRES is reading from the screen, its
  492. position is restored when you press [Enter] or [Esc].
  493.  
  494. You can interrupt the full screen speech by pressing any key.
  495.  
  496. If you activate STRES while in graphics mode, it will say "not in text mode."
  497.  
  498. You can type STRES /? for a summary of options and commands. Or type
  499. STRES /S /? for a spoken summary.
  500.  
  501. STRES.PAS requires TurboPower Software's Object Professional library (see
  502. below) to compile. STRES.EXE is provided in this same archive.
  503.  
  504.  
  505. About TurboPower Software
  506. ---------------------------------------------------------------------------
  507. TurboPower Software develops and markets add-on packages that make Turbo
  508. Pascal programmers more productive. Here's a brief description of current
  509. products:
  510.  
  511. Object Professional
  512.   An object-oriented library of over 100 object types and 2000 methods for
  513.   writing sophisticated text mode user interfaces, for creating memory
  514.   resident programs, and for solving many other common programming problems.
  515.   Requires Turbo Pascal 5.5. List price $150.
  516.  
  517. Turbo Professional
  518.   The non-object-oriented predecessor to Object Professional. Has most of the
  519.   same capabilities. Requires Turbo Pascal 4.0 or later. List price $125.
  520.  
  521. B-Tree Filer
  522.   A library of routines for writing single or multi-user database applications
  523.   in Turbo Pascal. Also includes routines for direct access of network
  524.   capabilities such as message passing and print spooler control. Supports all
  525.   common PC networks. Requires Turbo Pascal 4.0 or later. List price $125 for
  526.   the single user version, $175 with network support.
  527.  
  528. Turbo Analyst
  529.   A collection of utilities for documenting, analyzing, and improving Turbo
  530.   Pascal programs. Includes cross-referencing, program indexing, program
  531.   listing, pretty printing, execution profiling, and an integrated environment
  532.   to make the whole process easy and pleasant. Supports Turbo Pascal 4.0 or
  533.   later. List price $99.
  534.  
  535. TurboPower also publishes the BIGED ("Big Ed") text editor, which displays
  536. text in graphics mode at larger than normal sizes for vision-impaired computer
  537. users. We will soon release a shareware version of BIGED that also provides
  538. speech output using the Covox Speech Thing.
  539.  
  540. For further information, contact TurboPower at:
  541.  
  542.   TurboPower Software
  543.   P.O. Box 66747
  544.   Scotts Valley, CA 95067
  545.  
  546.   tel: 408-438-8608
  547.   fax: 408-438-8610
  548.   CompuServe: 76004,2611
  549.  
  550.  
  551.          ----------------end-of-author's-documentation---------------
  552.  
  553.                          Software Library Information:
  554.  
  555.                     This disk copy provided as a service of
  556.  
  557.                            Public (software) Library
  558.  
  559.          We are not the authors of this program, nor are we associated
  560.          with the author in any way other than as a distributor of the
  561.          program in accordance with the author's terms of distribution.
  562.  
  563.          Please direct shareware payments and specific questions about
  564.          this program to the author of the program, whose name appears
  565.          elsewhere in  this documentation. If you have trouble getting
  566.          in touch with the author,  we will do whatever we can to help
  567.          you with your questions. All programs have been tested and do
  568.          run.  To report problems,  please use the form that is in the
  569.          file PROBLEM.DOC on many of our disks or in other written for-
  570.          mat with screen printouts, if possible.  PsL cannot debug pro-
  571.          programs over the telephone, though we can answer questions.
  572.  
  573.          Disks in the PsL are updated  monthly,  so if you did not get
  574.          this disk directly from the PsL, you should be aware that the
  575.          files in this set may no longer be the current versions. Also,
  576.          if you got this disk from another vendor and are having prob-
  577.          lems,  be aware that  some files may have become corrupted or
  578.          lost by that vendor. Get a current, working disk from PsL.
  579.  
  580.          For a copy of the latest monthly software library newsletter
  581.          and a list of the 2,000+ disks in the library, call or write
  582.  
  583.                            Public (software) Library
  584.                                P.O.Box 35705 - F
  585.                             Houston, TX 77235-5705
  586.  
  587.                                 1-800-2424-PSL
  588.                              MC/Visa/AmEx/Discover
  589.  
  590.                           Outside of U.S. or in Texas
  591.                           or for general information,
  592.                               Call 1-713-524-6394
  593.  
  594.                           PsL also has an outstanding
  595.                           catalog for the Macintosh.
  596.  
  597.